import React, {FC, useCallback, useEffect, useMemo, useRef, useState} from "react";
import "./css/MenuAdd.less";
import {Button, Input, InputNumber, Select, Spin, Switch, Table} from "antd";
import {getLocale} from "../../../../i18n/i18n";
import {useTranslation} from "react-i18next";
import useStateRef from "../../../customUse/useStateRef";
import useThrottle from "../../../customUse/useThrottle";
import GlobalIcon from "../../../global/GlobalIcon.tsx";
import {addOkModal, closeModal} from "../../../services/ModalService.tsx";
import {AxiosSer} from "../../../services/HttpService.tsx";
import {getFormView} from "../../../services/ViewService.tsx";
import {coreDispatch} from "../../../utils/StoreUtil.tsx";
import MenuConfig from "./MenuConfig.tsx";
import {showMessage} from "../../../reducer/MsgReducer.tsx";

interface MenuAddProps {
    type: string,
    modalKey: string,
    flowData: any[],
    dataSource: any,
}

const MenuAdd: FC<MenuAddProps> = (props) => {
    const {t} = useTranslation();

    const selectMap: object = {
        menuType: {
            arr: [
                {
                    label: t("menu"),
                    value: "MENU"
                }, {
                    label: t("button"),
                    value: "BUTTON"
                }, {
                    label: t("virtuallyMenu"),
                    value: "VirtualMenu"
                }
            ],
            map: {
                "MENU": t("menu"),
                "BUTTON": t("button"),
                "VirtualMenu": t("virtuallyMenu"),
            }
        }
    };


    const dataRef = useRef([]);

    const [columns, setColumns] = useState<any[]>([]),
        [dataSource, setDataSource] = useStateRef([], dataRef),
        [isShowVirtuallyMenu, setIsShowVirtuallyMenu] = useState<boolean>(false),
        [loading, setLoading] = useState<boolean>(false);

    const isCreate: Function = useCallback(() => {
        return props.type === "create";
    }, [props.type]);

    const handleChange: Function = (index: number, field: string, value: string) => {
        let row = [...dataRef.current];
        let node: any = row[index];
        node[field] = value;
        setDataSource(row);

        if (field === "menuType" && value === 'VirtualMenu' && !isShowVirtuallyMenu) {
            setIsShowVirtuallyMenu(true);
        }
    };

    const handleChangeIndex: Function = (index: number, change: number) => {
        let targetI: number = index + change,
            row: any = [...dataRef.current],
            tempIRow: any = row[index];
        if (targetI < (isCreate() ? 0 : 1) || targetI > row.length - 1) {
            return;
        }

        row.splice(index, 1, row[targetI]);
        row.splice(targetI, 1, tempIRow);

        setDataSource(row);
    };

    const handleEditConfig: Function = (index: number, node: any) => {
        coreDispatch("modalReducer/createModal", {
            key: "editMenuConfig",
            modalProps: {
                title: t("editMenuConfig"),
                width: 1000,
            },
            component: MenuConfig,
            comProps: {
                value: node.config
            },
            onFinish: (result: any) => {
                if (result) {
                    handleChange(index, 'config', result)
                }
            }
        })
    }

    const handleDelete: Function = (index: number) => {
        let row = [...dataRef.current];
        row.splice(index, 1);
        setDataSource(row);
    };

    const handleAdd: Function = useCallback(() => {
        const {flowData} = props;
        let newNode = {
            id: Math.random(),
            optType: "add",
            parentId: flowData[0] ? flowData[0].id : undefined
        };
        setDataSource([...dataSource, newNode])
    }, [dataSource]);

    const onOk: Function = useThrottle(async () => {
        let requireAttrs: string[] = ["name", "zhCn", "usEn", "ptBr", "orderNo", "menuType"];
        if (isShowVirtuallyMenu) {
            requireAttrs = [...requireAttrs, "objectTypeName", "objectStatusId"];
        }

        let submitList: any[] = [];
        dataRef.current.forEach((item: any) => {
            if (item.optType !== "view") {
                let node: object = {
                    id: item.optType === "add" ? undefined : item.id,
                    parentId: item.parentId,
                    name: item.name,
                    zhCn: item.zhCn,
                    usEn: item.usEn,
                    ptBr: item.ptBr,
                    orderNo: item.orderNo,
                    config: item.config,
                    isOutside: !!item.isOutside,
                    isShowMenu: !!item.isShowMenu,
                    menuType: item.menuType,
                    description: item.description,
                };
                if (isShowVirtuallyMenu) {
                    node = {
                        ...node,
                        objectTypeName: item.objectTypeName,
                        objectStatusId: item.objectStatusId
                    }
                }
                submitList.push(node)
            }
        });

        for (let item of submitList) {
            for (let attrName of requireAttrs) {
                if (item[attrName] === undefined || item[attrName] === null) {
                    showMessage({
                        type: "error",
                        msg: t("notNullValue")
                    })
                    return;
                }
            }
        }
        setLoading(true);
        let result: any = await AxiosSer('/sf-drs/platform/menus', isCreate() ? "POST" : "PUT", {menus: submitList});
        setLoading(false);
        result.code == "1" && await closeModal(props.modalKey, async () => {
            return {data: submitList, ...result};
        })

    }, 2000, [dataSource, isShowVirtuallyMenu]);


    const createEditInput: Function = useCallback((field: string, width: number) => {
        return (text: string, node: any, index: number) => {

            if (node.optType === "view") {
                return <div style={{overflowX: "auto", maxWidth: width}}>{text}</div>
            }

            return <Input.TextArea rows={1} style={{width: "100%"}} value={text} onChange={e => {
                handleChange(index, field, e.target.value)
            }}/>;
        }
    }, []);

    const createEditInputNumber: Function = useCallback((field: string) => {
        return (text: string, node: any, index: number) => {

            if (node.optType === "view") {
                return <div>{text}</div>
            }

            return <InputNumber style={{width: "100%"}} value={text} onChange={value => {
                handleChange(index, field, value)
            }}/>;
        }
    }, []);

    const createEditSelect: Function = useCallback((field: string) => {
        return (text: string, node: any, index: number) => {

            if (["view", "edit", "parent"].indexOf(node.optType) !== -1) {
                return <div>{selectMap[field].map[text]}</div>
            }

            return <Select style={{width: "100%"}} value={text} onChange={value => {
                handleChange(index, field, value)
            }} options={selectMap[field].arr || []}/>;
        }
    }, []);

    const createEditSwitch: Function = useCallback((field: string) => {
        return (text: boolean, node: any, index: number) => {
            return <Switch style={{width: "100%"}} checked={text} onChange={value => {
                handleChange(index, field, value)
            }}/>;
        }
    }, []);

    const createOpt: Function = useCallback(() => {
        return (text: string, node: any, i: number) => {
            let isCreateType: boolean = isCreate();

            if (!isCreateType && !i) {
                return (<Button.Group>
                    <Button icon={<GlobalIcon name="icon-edit"/>} onClick={() => handleEditConfig(i, node)}/>
                </Button.Group>)
            }

            return (<Button.Group>
                <Button icon={<GlobalIcon name="icon-put-away"/>} onClick={() => handleChangeIndex(i, -1)}/>
                <Button icon={<GlobalIcon name="icon-launch"/>} onClick={() => handleChangeIndex(i, 1)}/>
                <Button icon={<GlobalIcon name="icon-edit"/>} onClick={() => handleEditConfig(i, node)}/>
                {isCreateType && node.optType !== "view" ? (
                    <Button icon={<GlobalIcon name="icon-delete"/>} onClick={() => handleDelete(i)}/>) : null}
            </Button.Group>)
        }
    }, []);

    const loadColumns: Function = useCallback(async () => {
        let columns: any[] = [];
        let {form = []}: { form: any } = await getFormView("form_menu_create");
        columns = form.map((item: any) => {
            let width = 150,
                renderCom: Function;

            if (item.field === "menuType") {
                renderCom = createEditSelect(item.field, width);
            } else if (item.field === "orderNo") {
                width = 80;
                renderCom = createEditInputNumber(item.field);
            } else if (item.field === "isOutside") {
                width = 50;
                renderCom = createEditSwitch(item.field);
            } else if (item.field === "isShowMenu") {
                width = 50;
                renderCom = createEditSwitch(item.field);
            }
            if (!renderCom) {
                renderCom = createEditInput(item.field, width);
            }
            return {
                title: item.title,
                dataIndex: item.field,
                align: "center",
                width: width,
                render: renderCom,
                show: item.hidden
            }
        });
        columns.push({
            title: t("opt"),
            dataIndex: "opt",
            width: 120,
            render: createOpt(),
            show: false
        });
        setColumns(columns);
    }, []);

    const loadData: Function = useCallback(() => {
        const {flowData = []}: { flowData: any[] } = props;

        let row: any[] = [];
        let child: any[] = flowData[0] && flowData[0].children && flowData[0].children.length ? flowData[0].children : null;

        if (child) {
            row = child.map((item: any) => {
                return {
                    id: item.id,
                    parentId: flowData[0].id,
                    name: item.name,
                    zhCn: item.zhCn,
                    usEn: item.usEn,
                    ptBr: item.ptBr,
                    orderNo: item.orderNo,
                    config: item.config,
                    menuType: item.menuType,
                    isOutside: item.isOutside,
                    isShowMenu: item.isShowMenu,
                    description: item.description,
                    objectTypeName: item.objectTypeName,
                    objectStatusId: item.objectStatusId,
                    optType: isCreate() ? "view" : "edit"
                }
            });
            if (!isCreate()) {
                row.unshift({
                    id: flowData[0].id,
                    name: flowData[0].name,
                    zhCn: flowData[0].zhCn,
                    usEn: flowData[0].usEn,
                    ptBr: flowData[0].ptBr,
                    orderNo: flowData[0].orderNo,
                    config: flowData[0].config,
                    isOutside: flowData[0].isOutside,
                    isShowMenu: flowData[0].isShowMenu,
                    description: flowData[0].description,
                    menuType: flowData[0].menuType,
                    optType: "parent"
                })
            }
            if (child.findIndex((i: any) => (i.menuType === "VirtualMenu")) !== -1) {
                setIsShowVirtuallyMenu(true);
            }
        } else {
            if (!isCreate()) {
                row = [{
                    id: flowData[0].id,
                    name: flowData[0].name,
                    zhCn: flowData[0].zhCn,
                    usEn: flowData[0].usEn,
                    ptBr: flowData[0].ptBr,
                    orderNo: flowData[0].orderNo,
                    config: flowData[0].config,
                    isOutside: flowData[0].isOutside,
                    isShowMenu: flowData[0].isShowMenu,
                    description: flowData[0].description,
                    menuType: flowData[0].menuType,
                }]
            } else {
                row = [{
                    id: Math.random(),
                    optType: "add",
                    parentId: flowData[0] ? flowData[0].id : undefined
                }]
            }
        }


        setDataSource(row);
    }, [props]);

    useEffect(() => {
        loadColumns();
        loadData()
    }, []);

    useEffect(() => {
        addOkModal(props.modalKey, onOk);
    }, [isShowVirtuallyMenu]);

    const renderMenuAdd = useMemo(() => {
        const {flowData = []}: { flowData: any[] } = props;

        return (
            <Spin spinning={loading} wrapperClassName="sf_core_menu_add">
                <Table
                    columns={columns.filter(item => isShowVirtuallyMenu || !item.show)}
                    dataSource={dataRef.current}
                    pagination={false}
                    size={'small'}
                    bordered={true}
                    rowKey={'id'}
                    title={() => {
                        if (!flowData.length) {
                            return null;
                        }
                        return <div
                            className="sf_core_menu_add_title">{getLocale(flowData[0].zhCn, flowData[0].usEn, flowData[0].ptBr)} --- {flowData[0].name}</div>
                    }}
                    footer={() => {

                        if (!isCreate()) {
                            return null;
                        }

                        return (
                            <div className="sf_core_lov_footer">
                                <Button onClick={handleAdd}
                                        icon={<GlobalIcon style={{fontSize: 10}}
                                                          name="icon-create"/>}>{t("add")}</Button>
                            </div>
                        )
                    }}
                />
            </Spin>
        )
    }, [loading, columns, dataSource, props, isShowVirtuallyMenu]);

    return (renderMenuAdd);
};

export default MenuAdd;